package org.hxzon.cyclone.fgen;

import org.hxzon.cyclone.RigidBody;
import org.hxzon.cyclone.Util;
import org.hxzon.cyclone.Vector3;

//fgen.h,fgen.cpp
//弹力
public class Spring implements ForceGenerator {
    /**
     * The point of connection of the spring, in local
     * coordinates.
     */
    private Vector3 connectionPoint;

    /**
     * The point of connection of the spring to the other object,
     * in that object's local coordinates.
     */
    private Vector3 otherConnectionPoint;

    /** The particle at the other end of the spring. */
    private RigidBody other;//pointer

    private double springConstant;//弹簧系统

    private double restLength;//弹簧自然长度

    public Spring(Vector3 localConnectionPt, RigidBody other, Vector3 otherConnectionPt, double springConstant, double restLength) {
        this.connectionPoint = localConnectionPt;
        this.otherConnectionPoint = otherConnectionPt;
        this.other = other;
        this.springConstant = springConstant;
        this.restLength = restLength;
    }

    public void updateForce(RigidBody body, double duration) {
        // Calculate the two ends in world space
        Vector3 lws = body.getPointInWorldSpace(connectionPoint);
        Vector3 ows = other.getPointInWorldSpace(otherConnectionPoint);

        // Calculate the vector of the spring
        Vector3 force = lws.minus(ows);

        // Calculate the magnitude of the force
        double magnitude = force.magnitude();
        magnitude = Util.realAbs(magnitude - restLength);
        magnitude *= springConstant;

        // Calculate the final force and apply it
        force.normalise();
        force.multiUpdate(-magnitude);
        body.addForceAtPoint(force, lws);
    }
}
